import uuid from 'es6-uuid';
import SockJS from 'sockjs-client'; // 使用http的连接方式进行socket信息推送
import Stomp from 'stompjs';

let stompClient = ''; // 双向连接对象
let heartTestObj = ''; // 心跳测试的轮询对象
const heartTime = 5000; // 心跳测试时间（5秒钟）
let obj = null;

// 提供一个创建websocket连接的公共方法
function NewWebSocket({
  subscribeUrl = '', // 订阅的后台返回数据的url(必传)
  url = '', // websocket的url连接(必传)
  connectCall = () => {}, // 连接状态变更的回调方法
  callback = () => {}, // 收到服务端消息的回调方法
  id = uuid(8), // 用于订阅的唯一的标识
} = {}) {
  // 对外提供的初始化方法
  function connect() {
    init();

    // 断开重连机制,尝试发送消息,捕获异常发生时重连
    heartTestObj = setInterval(() => {
      try {
        // 主动心跳测试
        stompClient.send('心跳测试');
      } catch (err) {
        // 抛出连接失败事件
        connectCall(false);

        console.error(`websocket心跳测试失败，将重新发起连接，失败原因：${err}: `);

        // 心跳失败，重新初始websocket连接
        init();
      }
    }, heartTime);
  }

  // 执行websocket连接
  function init() {
    // 定义客户端的认证信息,按需求配置
    const headers = { Authorization: '' };

    // 建立连接对象（还未发起连接）
    const socket = new SockJS(url);

    // 获取stomp子协议的客户端对象
    stompClient = Stomp.over(socket);

    // 向服务器发起websocket连接，并发送CONNECT帧
    stompClient.connect(
      headers,
      () => {
        // 订阅
        obj = stompClient.subscribe(
          subscribeUrl,
          (msg) => {
            console.log('收到服务端消息', obj);

            // msg.body存放的是服务端发送给我们的信息
            callback(msg);
          },
          { id },
        );

        // 抛出连接成功事件
        connectCall(true);

        console.log('------------websocket连接成功！--------------');
      },
      (err) => {
        // 连接发生错误时的处理函数
        console.error(`webSocket连接失败！失败原因：${err}`);
      },
    );
  }

  // 客户端向服务端发送消息
  function send(url, params, paramsStr) {
    // 连接成功后，客户端可使用 send() 方法向服务器发送信息
    stompClient.send(
      url, // 为服务器 controller中 @MessageMapping 中匹配的URL（必填）
      params, // 条件参数（选填）  需要填写的是对象
      paramsStr, // 条件参数 对象需要JSON.stringify一下
    );
  }

  // 取消订阅事件
  function unsubscribe() {
    console.log('取消订阅');
    // 关闭心跳测试的轮询
    heartTestObj && clearInterval(heartTestObj);
    obj.unsubscribe();
  }
  // 继续订阅
  function subscribe() {
    stompClient &&
      stompClient.subscribe(
        subscribeUrl,
        (msg) => {
          console.log('收到服务端消息', obj);

          // msg.body存放的是服务端发送给我们的信息
          callback(msg);
        },
        { id },
      );
  }

  // 断开连接
  function disconnect() {
    // 关闭心跳测试的轮询
    heartTestObj && clearInterval(heartTestObj);
    // 断开连接，删除websocket对象
    if (stompClient != null) {
      stompClient.disconnect && stompClient.disconnect(); // 关闭连接
      stompClient = null; // 删除双向连接对象

      // 抛出取消连接事件
      connectCall(false);
    }

    console.log('------------websocket断开连接！--------------');
  }

  return {
    connect, // 初始化连接
    send, // 客户端向服务端发送消息
    disconnect, // 断开连接
    unsubscribe, // 取消订阅
    subscribe, // 建立订阅
  };
}
export default NewWebSocket;
